package com.zmn.oms.zmn.business.impl.quotation3;

import com.alibaba.fastjson.JSON;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.zmn.base.common.data.common.dro.fault.FaultDRO;
import com.zmn.base.common.data.common.dro.maintainitem.MaintainDRO;
import com.zmn.base.common.data.common.dro.maintainitem.MaintainItemDRO;
import com.zmn.base.common.data.common.dro.servicecontent.ServiceContentDRO;
import com.zmn.base.common.data.common.query.maintainitem.MaintainItemQuery;
import com.zmn.base.common.data.dubbo.interfaces.fault.FaultListRemoteService;
import com.zmn.base.common.data.dubbo.interfaces.maintainitem.MaintainItemListRemoteService;
import com.zmn.base.price.common.constant.ItemAdditionConst;
import com.zmn.base.price.common.dro.item.ItemAdditionDRO;
import com.zmn.base.price.common.dro.item.ItemPartsDRO;
import com.zmn.base.price.common.dto.item.ItemCellDRO;
import com.zmn.base.price.common.dto.item.ItemDRO;
import com.zmn.base.price.common.dto.item.ItemQuoteQuery;
import com.zmn.base.price.common.dto.meter3.MeterBaseQuery;
import com.zmn.base.price.common.dto.meter3.MeterContentQuery;
import com.zmn.base.price.dubbo.interfaces.calculate.ItemPriceRemoteService;
import com.zmn.base.price.dubbo.interfaces.calculate.MeterFlow3RemoteService;
import com.zmn.base.price.dubbo.interfaces.item.ItemAdditionRemoteService;
import com.zmn.base.price.dubbo.interfaces.item.ItemPartsRemoteService;
import com.zmn.base.product.common.dto.categ.FaultImageDRO;
import com.zmn.base.product.dubbo.interfaces.categ.serv.CategRelationFaultImageListRemoteService;
import com.zmn.base.shortlink.common.constant.DubboConsts;
import com.zmn.base.shortlink.common.dio.shortlink.ShortLinkDIO;
import com.zmn.base.shortlink.common.dro.shortlink.ShortLinkDRO;
import com.zmn.base.shortlink.dubbo.interfaces.shortlink.ShortLinkModifyRemoteService;
import com.zmn.biz.engineer.dubbo.interfaces.discount.EngineerDiscountModifyRemoteService;
import com.zmn.common.dto2.AMISListData;
import com.zmn.common.dto2.ResponseDTO;
import com.zmn.common.utils.collection.CollectionUtil;
import com.zmn.common.utils.date.DateUtil;
import com.zmn.common.utils.number.NumberUtil;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.common.utils.string.StringUtil;
import com.zmn.consts.GlobalConsts;
import com.zmn.dms.common.dto.promotion.dio.Meter3ArtificialPromQuery;
import com.zmn.dms.common.dto.promotion.dio.ReceiveMeter3ArtificialPromDIO;
import com.zmn.dms.common.dto.promotion.dio.SendMeter3ArtificialPromDIO;
import com.zmn.dms.common.dto.promotion.dro.Meter3ArtificialPromDRO;
import com.zmn.dms.dubbo.interfaces.prom.Meter3ArtificialPromListRemoteService;
import com.zmn.dms.dubbo.interfaces.prom.Meter3ArtificialPromModifyRemoteService;
import com.zmn.manager.mq.interfaces.ZmnMQSender;
import com.zmn.manager.redis.RedisManager;
import com.zmn.mos.common.constant.MosErrorCodeConsts;
import com.zmn.oms.business.interfaces.log.OrderLogBService;
import com.zmn.oms.business.interfaces.messageV1.common.MessageGetSendInfoService;
import com.zmn.oms.business.interfaces.messageV1.common.MessageSendBaseService;
import com.zmn.oms.business.interfaces.messageV1.wechat.MessageWeChatTemplateService;
import com.zmn.oms.business.interfaces.operation.OrderOperationBService;
import com.zmn.oms.business.interfaces.orderamount.OrderAmountBService;
import com.zmn.oms.business.interfaces.orderamount.OrderAmountCalcBService;
import com.zmn.oms.business.interfaces.part.OrderPartBService;
import com.zmn.oms.business.interfaces.work.OrderWorkAmountBService;
import com.zmn.oms.business.interfaces.work.tag.OrderTagBService;
import com.zmn.oms.common.annotation.ZsNormalOrderWorkLog;
import com.zmn.oms.common.constant.*;
import com.zmn.oms.common.dio.quotation3.*;
import com.zmn.oms.common.dro.quotation3.OperateResultDRO;
import com.zmn.oms.common.dto.OmsBaseOperator;
import com.zmn.oms.common.dto.OmsOperator;
import com.zmn.oms.common.enums.ServiceItemTypeEnum;
import com.zmn.oms.common.exception.OmsBaseException;
import com.zmn.oms.common.utils.DateTimeUtil;
import com.zmn.oms.model.bo.orderamount.OrderAmountCalcBO;
import com.zmn.oms.model.bo.orderamount.ReCalcOrderAmountDIO;
import com.zmn.oms.model.dto.messageV1.AppMessageDTO;
import com.zmn.oms.model.dto.messageV1.SmsMessageDTO;
import com.zmn.oms.model.dto.part.SingleMasterOrderPartDTO;
import com.zmn.oms.model.dto.serviceitem.AddOrderServiceItemDTO;
import com.zmn.oms.model.dto.work.modify.amount.ZsDiscountDTO;
import com.zmn.oms.model.entity.detail.OrderDetail;
import com.zmn.oms.model.entity.log.OrderLog;
import com.zmn.oms.model.entity.operation.OrderOperation;
import com.zmn.oms.model.entity.orderappbind.OrderThirdAppBind;
import com.zmn.oms.model.entity.orderfinalpricequotation.OrderFinalPriceQuotation;
import com.zmn.oms.model.entity.orderfinalpricequotation.OrderFinalPriceQuotationQuery;
import com.zmn.oms.model.entity.product.OrderProduct;
import com.zmn.oms.model.entity.product.OrderProductExtend;
import com.zmn.oms.model.entity.quotation3.*;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItem;
import com.zmn.oms.model.entity.serviceitem.OrderServiceItemCell;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.discount.OrderDiscountService;
import com.zmn.oms.services.interfaces.orderencrypt.OrderEncryptService;
import com.zmn.oms.services.interfaces.orderfinalpricequotation.OrderFinalPriceQuotationService;
import com.zmn.oms.services.interfaces.product.OrderProductExtendService;
import com.zmn.oms.services.interfaces.product.OrderProductService;
import com.zmn.oms.services.interfaces.quotation3.*;
import com.zmn.oms.services.interfaces.serviceitem.OrderServiceItemService;
import com.zmn.oms.services.interfaces.warranty.OrderWarrantyService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.zmn.aop.OrderWorkLogUtils;
import com.zmn.oms.zmn.business.interfaces.captcha.OrderWorkCaptchaBService;
import com.zmn.oms.zmn.business.interfaces.quotation3.OrderQuotation3ListBService;
import com.zmn.oms.zmn.business.interfaces.quotation3.OrderQuotation3ModifyBService;
import com.zmn.oms.zmn.business.interfaces.warranty.ZsOrderWarrantyBService;
import com.zmn.oms.zmn.business.interfaces.work.masterwork.ZsMasterWorkBService;
import com.zmn.oms.zmn.normal.business.interfaces.discount.ZsNormalOrderDiscountBService;
import com.zmn.scm2.common.model.dro.scm.purchase.apply.ScmPurchaseApplyDRO;
import com.zmn.scm2.common.model.query.scm.purchase.apply.ScmPurchaseApplyQuery;
import com.zmn.scm2.dubbo.interfaces.scm.engineer.purchase.EngineerPurchaseListRemoteService;
import com.zmn.uuc.dubbo.interfaces.user.UserThirdListRemoteService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author sunlife
 * @date:2021/12/1 6:44 下午
 * description:
 */
@Service
@Slf4j
public class OrderQuotation3ModifyBServiceImpl implements OrderQuotation3ModifyBService {

    @Autowired
    private RedisManager redisManager;
    @Autowired
    private OrderQuotation3ModifyBService orderQuotation3ModifyBService;
    @Autowired
    private OrderWorkService orderWorkService;
    @Autowired
    private OrderProductService orderProductService;
    @Autowired
    private OrderQuotationProcessService orderQuotationProcessService;
    @Autowired
    private ZsOrderWarrantyBService zsOrderWarrantyBService;
    @Autowired
    private OrderFaultPhenomenonService orderFaultPhenomenonService;
    @Autowired
    private OrderFaultService orderFaultService;
    @Autowired
    private OrderMaintainItemService orderMaintainItemService;
    @Autowired
    private OrderQuotationServiceItemService orderquotationserviceitemService;
    @Autowired
    private OrderServiceContentService orderServiceContentService;
    @Autowired
    private ZsMasterWorkBService zsMasterWorkBService;
    @Autowired
    private OrderProductExtendService orderProductExtendService;
    @Autowired
    private MessageWeChatTemplateService messageWeChatTemplateService;
    @Autowired
    private OrderWorkCaptchaBService orderWorkCaptchaBService;
    @Autowired
    private MessageSendBaseService messageSendBaseService;
    @Autowired
    private ZsNormalOrderDiscountBService zsNormalOrderDiscountBService;
    @Autowired
    private OrderAcceptMaintainItemService orderAcceptMaintainItemService;
    @Autowired
    private OrderServiceItemService orderServiceItemService;
    @Autowired
    private OrderAmountCalcBService orderAmountCalcBService;
    @Autowired
    private OrderWorkAmountBService orderWorkAmountBService;
    @Autowired
    private OrderLogBService orderLogBService;
    @Autowired
    private OrderTagBService orderTagBService;
    @Autowired
    private OrderAmountBService orderAmountBService;
    @Autowired
    private OrderOperationBService orderOperationBService;
    @Autowired
    private OrderWarrantyService orderWarrantyService;
    @Autowired
    private OrderQuotation3ListBService orderQuotation3ListBService;
    @Autowired
    private OrderDetailService orderDetailService;
    @Autowired
    OrderEncryptService orderEncryptService;
    @Autowired
    OrderPartBService orderPartBService;
    @Autowired
    protected MessageGetSendInfoService messageGetSendInfoService;
    @Autowired
    private OrderDiscountService orderDiscountService;

    @Resource
    private OrderFinalPriceQuotationService orderFinalPriceQuotationService;

    @Resource
    ZmnMQSender zmnMQSender;


    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private MeterFlow3RemoteService meterFlow3RemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private FaultListRemoteService faultListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private CategRelationFaultImageListRemoteService categRelationFaultImageListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION , check = false)
    private MaintainItemListRemoteService maintainItemRemoteService;
    @Reference(version = com.zmn.dms.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private Meter3ArtificialPromModifyRemoteService meter3ArtificialPromModifyRemoteService;
    @Reference(version = DubboConsts.INTERFACE_VERSION, check = false)
    private ShortLinkModifyRemoteService shortLinkModifyRemoteService;
    @Reference(version = com.zmn.dms.dubbo.utils.DubboConsts.INTERFACE_VERSION, check = false)
    private Meter3ArtificialPromListRemoteService meter3ArtificialPromListRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private ItemAdditionRemoteService itemAdditionRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private ItemPriceRemoteService itemPriceRemoteService;
    @Reference(version = com.zmn.base.plat.engine.common.constant.DubboConsts.INTERFACE_VERSION, check = false)
    private ItemPartsRemoteService itemPartsRemoteService;
    @Reference(version = com.zmn.scm2.dubbo.interfaces.utils.DubboConsts.INTERFACE_VERSION, check = false)
    EngineerPurchaseListRemoteService engineerPurchaseListRemoteService;
    @DubboReference(version = com.zmn.uuc.common.constant.DubboConsts.INTERFACE_VERSION,check = false)
    private UserThirdListRemoteService userThirdListRemoteService;
    @DubboReference(version = com.zmn.biz.engineer.common.constants.DubboConsts.INTERFACE_VERSION)
    private EngineerDiscountModifyRemoteService engineerDiscountModifyRemoteService;

    private static final int MOBILE_SEND_AGREE_REPAIR_LIMIT = 2;

    @NacosValue(value = "${order.master.discountUrl:''}", autoRefreshed = true) // 如果改变，自动刷新
    public String ORDER_MASTER_DISCOUNT_URL;
    @Value("${spring.profiles.active}")
    private String active;

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_START_CHECK)
    public void startCheck(OmsOperator operator) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(operator.getOrderId(), operator.getWorkId());
        this.commonVerify(orderWork);

        // 是否已确认产品
        OrderQuotationProcess process = orderQuotationProcessService.findByOrderId(operator.getOrderId());
        if (Objects.isNull(process) || !Objects.equals(process.getCheckProductStatus(), GlobalConsts.YES)) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "平台客服已修改产品信息，请重新确认产品");
        }

        if (Objects.isNull(process.getStartCheckTime())) {
            Date now = DateUtil.getNow();

            OrderQuotationProcess updateProcess = new OrderQuotationProcess();
            updateProcess.setOrderId(operator.getOrderId());
            updateProcess.setStartCheckTime(now);

            updateProcess.setUpdater(operator.getOperator());
            updateProcess.setUpdateTime(now);
            orderQuotationProcessService.updateByOrderIdSelective(updateProcess);
        }
    }

    @Override
    public OperateResultDRO confirmCheckType(ConfirmCheckTypeDIO dio) throws OmsBaseException {
        if (NumberUtil.isNullOrZero(dio.getCheckType())) {
            dio.setCheckType(OrderQuotation3Constant.CHECK_TYPE_ARTIFICIAL);
        }
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(dio.getOrderId(), dio.getWorkId());
        this.commonVerify(orderWork);

        // 是否已确认产品
        OrderQuotationProcess process = orderQuotationProcessService.findByOrderId(dio.getOrderId());

        if (Objects.isNull(process) || !Objects.equals(process.getCheckProductStatus(), GlobalConsts.YES)) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "平台客服已修改产品信息，请重新确认产品");
        }
        // 如果检修类型不变，不处理，直接返回成功
        if (Objects.equals(process.getCheckType(), dio.getCheckType())) {
            return new OperateResultDRO(false);
        }

        Date now = DateUtil.getNow();

        if (Objects.equals(OrderQuotation3Constant.CHECK_TYPE_AI, dio.getCheckType())) {
            // AI 检测

        } else {
            // 人工检修

        }

        // 更新相关数据
        OrderQuotationProcess updateProcess = new OrderQuotationProcess();
        updateProcess.setOrderId(dio.getOrderId());
        updateProcess.setCheckType(dio.getCheckType());
        updateProcess.setUpdater(dio.getOperator());
        updateProcess.setUpdateTime(now);
        orderQuotationProcessService.updateByOrderIdSelective(updateProcess);

        return new OperateResultDRO(true);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_USER_CONFIRM_FAULT_PHEN)
    public OperateResultDRO confirmFaultInfo(ConfirmFaultInfoDIO confirmFaultInfoDIO) throws OmsBaseException {
        if (StringUtils.isBlank(confirmFaultInfoDIO.getOperator()) || NumberUtil.isNullOrZero(confirmFaultInfoDIO.getOperatorType())) {
            throw new OmsBaseException(OmsErrorCodeConsts.PARAMS_OPERATOR_VERIFY_EXCEPTION, "操作人或操作人类型不能为空");
        }
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(confirmFaultInfoDIO.getOrderId(), confirmFaultInfoDIO.getWorkId());
        this.commonVerify(orderWork);

        OrderQuotationProcess process = orderQuotationProcessService.findByOrderId(confirmFaultInfoDIO.getOrderId());

        // 是否已确认产品
        if (Objects.isNull(process) || !Objects.equals(process.getCheckProductStatus(), GlobalConsts.YES)) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "平台客服已修改产品信息，请重新确认产品");
        }

        // 获取之前选择的故障现象
        List<OrderFaultPhenomenon> phenList = orderFaultPhenomenonService.listByOrderId(confirmFaultInfoDIO.getOrderId());
        if (CollectionUtil.isNotNullOrEmpty(phenList)) {
            List<Integer> dbPhenIdList = phenList.stream().map(OrderFaultPhenomenon::getPhenId).collect(Collectors.toList());
            List<Integer> phenIdList = confirmFaultInfoDIO.getPhenList().stream().map(FaultPhenoDIO::getPhenId).collect(Collectors.toList());

            if (Objects.equals(dbPhenIdList.size(), phenIdList.size()) && dbPhenIdList.containsAll(phenIdList)) {
                // 如果完全一致 不修改相关数据
                return new OperateResultDRO(false);
            }
        }

        OrderProduct orderProduct = orderProductService.listOrderProductByOrderId(confirmFaultInfoDIO.getOrderId()).get(0);

        // 保留之前操作的某些信息
        Date startCheckTime = null;
        Integer checkProductStatus = GlobalConsts.NO;
        if (Objects.nonNull(process)) {
            startCheckTime = process.getStartCheckTime();
            checkProductStatus = process.getCheckProductStatus();
        }

        // 清空先前报价数据
        orderQuotation3ModifyBService.clearQuotationInfo(confirmFaultInfoDIO.getOrderId(), confirmFaultInfoDIO.getWorkId(), true);

        Date now = DateUtil.getNow();
        // 处理用户选择的故障现象
        // 储存故障现象
        List<OrderFaultPhenomenon> orderFaultPhenomenaList = Lists.newArrayList();

        // 查询故障现象相关信息
        List<Integer> phenIdList = confirmFaultInfoDIO.getPhenList().stream().map(FaultPhenoDIO::getPhenId).collect(Collectors.toList());
        Map<Integer, FaultPhenoDIO> phenDIOMap = confirmFaultInfoDIO.getPhenList().stream().collect(Collectors.toMap(FaultPhenoDIO::getPhenId, Function.identity(), (v1, v2) -> v1));

        // TODO 新接口？
        MeterBaseQuery meterBaseQuery = MeterBaseQuery
                .builder()
                .erpProductId(orderWork.getProductId())
                .bizType(orderWork.getBizType())
                .channelId(orderWork.getChannelId())
                .tariffId(orderProduct.getTariffId())
                .build();
        ResponseDTO<List<com.zmn.base.common.data.common.dro.phenomenon.PhenomenonDRO>> phenoResponseDTO = meterFlow3RemoteService.listPhenoByQuery(meterBaseQuery);
        if (!phenoResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(phenoResponseDTO.getData())) {
            throw new OmsBaseException(OmsErrorCodeConsts.CALL_THIRED_SYS_FAILED, phenoResponseDTO.getMessage());
        }
        Map<Integer, com.zmn.base.common.data.common.dro.phenomenon.PhenomenonDRO> phenomenonDROMap = phenoResponseDTO.getData().stream().collect(Collectors.toMap(com.zmn.base.common.data.common.dro.phenomenon.PhenomenonDRO::getPhenId, Function.identity(), (v1, v2) -> v1));

        phenIdList.forEach(phenId -> {
            OrderFaultPhenomenon phen = null;
            com.zmn.base.common.data.common.dro.phenomenon.PhenomenonDRO dro = phenomenonDROMap.get(phenId);
            if (Objects.nonNull(dro)) {
                phen = BeanMapper.map(dro, OrderFaultPhenomenon.class);
                phen.setDeteTime(dro.getMaintainTime());
            } else {
                phen = BeanMapper.map(phenDIOMap.get(phenId), OrderFaultPhenomenon.class);
                phen.setDeteTime(0);
            }

            if (Objects.isNull(phen.getDeteTime())) {
                phen.setDeteTime(0);
            }

            phen.setOrderId(confirmFaultInfoDIO.getOrderId());
            phen.setCreater(confirmFaultInfoDIO.getOperator());
            phen.setUpdater(confirmFaultInfoDIO.getOperator());
            phen.setCreateTime(now);
            phen.setUpdateTime(now);
            orderFaultPhenomenaList.add(phen);
        });
        orderFaultPhenomenonService.insertList(orderFaultPhenomenaList);

        // 记录报价流程信息
        OrderQuotationProcess orderQuotationProcess = new OrderQuotationProcess();
        orderQuotationProcess.setOrderId(confirmFaultInfoDIO.getOrderId());
        orderQuotationProcess.setConfirmStatus(GlobalConsts.YES);
        orderQuotationProcess.setConfirmTime(now);
        orderQuotationProcess.setStartCheckTime(startCheckTime);
        orderQuotationProcess.setCheckProductStatus(checkProductStatus);
        orderQuotationProcess.setCreater(confirmFaultInfoDIO.getOperator());
        orderQuotationProcess.setUpdater(confirmFaultInfoDIO.getOperator());
        orderQuotationProcess.setCreateTime(now);
        orderQuotationProcess.setUpdateTime(now);
        orderQuotationProcessService.updateByOrderIdSelective(orderQuotationProcess);

        if (Objects.equals(orderWork.getFinalPrice(),GlobalConsts.YES) && CollectionUtil.isNotNullOrEmpty(confirmFaultInfoDIO.getPhenList())){
            FaultPhenoDIO faultPhenoDIO = confirmFaultInfoDIO.getPhenList().get(0);
            List<OrderFinalPriceQuotation> orderFinalPriceQuotations = orderFinalPriceQuotationService
                    .listByQuery(OrderFinalPriceQuotationQuery.builder()
                    .workId(orderWork.getWorkId())
                    .orderId(orderWork.getOrderId())
                    .build());
            if (CollectionUtil.isNotNullOrEmpty(orderFinalPriceQuotations)){
                OrderFinalPriceQuotation orderFinalPriceQuotation = orderFinalPriceQuotations.get(0);
                if (!Objects.equals(faultPhenoDIO.getPhenId(),orderFinalPriceQuotation.getPhenId())){
                    OrderLog orderLog = new OrderLog();
                    orderLog.setTypeName("故障现象");
                    OrderWorkLogUtils.processOrderLogOperater(orderLog, confirmFaultInfoDIO);
                    orderLog.setOperatorTypeName(GlobalConsts.getOperatorTypeName(orderLog.getOperatorType()));
                    OrderWorkLogUtils.processOrderLogStatus(orderLog, orderWork, confirmFaultInfoDIO);
                    String dbPhenName = "";
                    if (CollectionUtil.isNotNullOrEmpty(phenList)){
                         dbPhenName = phenList.get(0).getPhenName();
                    }
                    orderLog.setContent("故障现象:" + dbPhenName + "->"+faultPhenoDIO.getPhenName());
                    orderLogBService.save(orderLog);
                }
            }
        }

        return new OperateResultDRO(true);
    }

    private void generateOrderMaintainItem(OmsBaseOperator operator, List<Integer> phenIdList) throws OmsBaseException {
        // 获取检修信息并存储
        log.info("获取检修项目 入参：{}", JSON.toJSONString(phenIdList));
        ResponseDTO<List<MaintainItemDRO>> maintainItemResponseDTO = maintainItemRemoteService.listMaintainItemByPhenIds(phenIdList);
        log.info("获取检修项目 出参：{}", JSON.toJSONString(maintainItemResponseDTO));
        if (!maintainItemResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(maintainItemResponseDTO.getData())) {
            throw new OmsBaseException(OmsErrorCodeConsts.CALL_THIRED_SYS_FAILED, maintainItemResponseDTO.getMessage());
        }
        List<MaintainItemDRO> maintainItemList = maintainItemResponseDTO.getData();
        List<OrderMaintainItem> orderMaintainItemList = Lists.newArrayListWithCapacity(maintainItemList.size());
        maintainItemList.forEach(maintainItemDRO -> {
            if (Objects.equals(maintainItemDRO.getStatus(), GlobalConsts.NO)) {
                return;
            }
            OrderMaintainItem maintainItem = BeanMapper.map(maintainItemDRO, OrderMaintainItem.class);
            maintainItem.setReferenceName(maintainItemDRO.getReferenceValue());
            maintainItem.setResult(GlobalConsts.NONE);
            maintainItem.setOrderId(operator.getOrderId());
            maintainItem.setCreater(operator.getOperator());
            maintainItem.setUpdater(operator.getOperator());
            maintainItem.setCreateTime(DateUtil.getNow());
            maintainItem.setUpdateTime(DateUtil.getNow());
            orderMaintainItemList.add(maintainItem);
        });
        orderMaintainItemService.insertList(orderMaintainItemList);
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_SUBMIT_CHECK_REPORT, beforeProceed = false)
    public void submitCheckReport(CheckReportDIO checkReportDIO) throws OmsBaseException {
        if (StringUtils.isBlank(checkReportDIO.getOperator()) || NumberUtil.isNullOrZero(checkReportDIO.getOperatorType())) {
            throw new OmsBaseException(OmsErrorCodeConsts.PARAMS_OPERATOR_VERIFY_EXCEPTION, "操作人或操作人类型不能为空");
        }

        OrderWork orderWork = orderWorkService.findOrderWorkByKey(checkReportDIO.getOrderId(), checkReportDIO.getWorkId());
        this.commonVerify(orderWork);

        OrderQuotationProcess dbProcess = orderQuotationProcessService.findByOrderId(checkReportDIO.getOrderId());
        if (Objects.isNull(dbProcess) || Objects.equals(dbProcess.getConfirmStatus(), GlobalConsts.NO)) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "订单状态不合法，请重新操作计价流程");
        }

        // 校验配件 一口价订单不校验配件
//        this.verifyPart(orderWork, checkReportDIO.getItemList());

//        if (Objects.equals(dbProcess.getReportConfirmStatus(), GlobalConsts.YES)) {
//            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "订单已生成检报告，不可操作");
//        }

        // 清空数据
        orderQuotation3ModifyBService.clearQuotationInfo(checkReportDIO.getOrderId(), checkReportDIO.getWorkId(), false);

        OrderProduct orderProduct = orderProductService.listOrderProductByOrderId(checkReportDIO.getOrderId()).get(0);

        List<OrderFaultPhenomenon> orderFaultPheno = orderFaultPhenomenonService.listByOrderId(checkReportDIO.getOrderId());
        List<Integer> phenIdList = orderFaultPheno.stream().map(OrderFaultPhenomenon::getPhenId).collect(Collectors.toList());

        Date now = DateUtil.getNow();

        // 处理检修项目
        List<Integer> maintainIdList = checkReportDIO.getMaintainItemList().stream().map(OrderMaintainItemDIO::getMaintainId).collect(Collectors.toList());
        MaintainItemQuery maintainItemQuery = new MaintainItemQuery();
        maintainItemQuery.setMaintainIds(maintainIdList);
        maintainItemQuery.setPageSize(100);

        log.info("获取检修项目 入参：{}", JSON.toJSONString(maintainItemQuery));
        ResponseDTO<AMISListData<MaintainDRO>> maintainItemResponseDTO = maintainItemRemoteService.listPageByQuery(maintainItemQuery);
        log.info("获取检修项目 出参：{}", JSON.toJSONString(maintainItemResponseDTO));
        if (!maintainItemResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(maintainItemResponseDTO.getData().getItems())) {
            throw new OmsBaseException(OmsErrorCodeConsts.CALL_THIRED_SYS_FAILED, maintainItemResponseDTO.getMessage());
        }
        Map<Integer, MaintainDRO> maintainDROMap = maintainItemResponseDTO.getData().getItems().stream().collect(Collectors.toMap(MaintainDRO::getMaintainId, Function.identity(), (v1, v2) -> v1));

        Map<Integer, OrderMaintainItemDIO> maintainDIOMap = checkReportDIO.getMaintainItemList().stream().collect(Collectors.toMap(OrderMaintainItemDIO::getMaintainId, Function.identity(), (v1, v2) -> v1));

        List<OrderMaintainItem> maintainItemList = Lists.newArrayList();
        for (OrderMaintainItemDIO dio : checkReportDIO.getMaintainItemList()) {
            // 校验
            MaintainDRO dro = maintainDROMap.get(dio.getMaintainId());

            if (Objects.isNull(dro)) {
                continue;
            }
            if (Objects.equals(dro.getCheck(), GlobalConsts.YES)) {
                if (Objects.isNull(dio.getSelectName())
                        || NumberUtil.isNullOrZero(dio.getSelectValue())) {
                    log.info("检修项目：{}", JSON.toJSONString(dio));
                    throw new OmsBaseException(MosErrorCodeConsts.PARAMS_VERIFY_EXCEPTION, "请选择故障检测的结果");
                }
            }
            OrderMaintainItem item = new OrderMaintainItem();
            item.setOrderId(checkReportDIO.getOrderId());
            item.setMaintainId(dro.getMaintainId());
            item.setMaintainName(dro.getMaintainName());
            item.setReferenceName(dro.getReferenceValue());
            item.setSelectedValue(dio.getSelectValue());
            item.setSelectedName(dio.getSelectName());
            item.setResult(dio.isStatus() ? GlobalConsts.YES : GlobalConsts.NO);
            maintainItemList.add(item);
        }

        orderMaintainItemService.insertList(maintainItemList);

        // 处理服务项
        ItemQuoteQuery itemQuoteQuery = ItemQuoteQuery
                .builder()
                .bizType(orderWork.getBizType())
                .channelId(orderWork.getChannelId())
                .cityId(orderWork.getCityId())
                .productId(orderWork.getProductId())
                .brandId(orderProduct.getBrandId())
                .tariffId(orderProduct.getTariffId())
                .itemList(checkReportDIO.getItemList()).build();
        ResponseDTO<List<ItemDRO>> itemResponseDTO = itemPriceRemoteService.listItemQuoteByQuery(itemQuoteQuery);
        log.info("计价器工单报价获取服务项：入参：{} 出参：{}", JSON.toJSONString(itemQuoteQuery), JSON.toJSONString(itemResponseDTO));
        if (!itemResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(itemResponseDTO.getData())) {
            throw new OmsBaseException(OmsErrorCodeConsts.CALL_THIRED_SYS_FAILED, itemResponseDTO.getMessage());
        }
        // 全部存储
        List<ItemDRO> itemDROList = itemResponseDTO.getData();
        List<OrderQuotationServiceItem> serviceItemList = Lists.newArrayListWithCapacity(itemDROList.size());
        itemDROList.forEach(item -> {
            OrderQuotationServiceItem serviceItem = new OrderQuotationServiceItem();
            serviceItem.setItemId(item.getItemId());
            serviceItem.setItemName(item.getItemName());
            serviceItem.setGroupId(item.getItemTypeId());
            serviceItem.setGroupName(item.getItemTypeName());
            serviceItem.setPrice(item.getPrice());
            serviceItem.setInternalSettlementSrice(item.getPriceInternalSettlement());
            serviceItem.setExternalSettlementPrice(item.getPriceExternalSettlement());
            serviceItem.setOrderId(checkReportDIO.getOrderId());
            serviceItem.setCreater(checkReportDIO.getOperator());
            serviceItem.setUpdater(checkReportDIO.getOperator());
            serviceItem.setCreateTime(now);
            serviceItem.setUpdateTime(now);
            serviceItemList.add(serviceItem);
        });
        orderquotationserviceitemService.batchInsert(serviceItemList);

        Map<Integer, List<ItemDRO>> faultServiceItemMap = Maps.newHashMap();

        itemDROList.forEach(itemDRO3 -> {
            if (StringUtils.isNotBlank(itemDRO3.getFault())) {
                String[] faultIdStrList = itemDRO3.getFault().split(",");
                for (int i = 0; i < faultIdStrList.length; i++) {
                    Integer faultId = Integer.valueOf(faultIdStrList[i]);
                    List<ItemDRO> itemDRO3List = faultServiceItemMap.get(faultId);
                    if (CollectionUtil.isNullOrEmpty(itemDRO3List)) {
                        itemDRO3List = Lists.newArrayList();
                        faultServiceItemMap.put(faultId, itemDRO3List);
                    }
                    itemDRO3List.add(itemDRO3);
                }
            }
        });

        // 处理故障图片数据
        ResponseDTO<List<FaultImageDRO>> imageResponseDTO = categRelationFaultImageListRemoteService.listFaultImageByServCategIdAndCategIdAndFaultIds(orderWork.getServCategId(), orderWork.getCategId(), checkReportDIO.getFaultIdList());
        log.info("获取故障图片数据入参：{}, {}, {}, 出参:{}", orderWork.getServCategId(), orderWork.getCategId(), checkReportDIO.getFaultIdList(), JSON.toJSONString(imageResponseDTO));
//        if (!imageResponseDTO.isSuccess()) {
//            throw new OmsBaseException(OmsErrorCodeConsts.CALL_THIRED_SYS_FAILED, imageResponseDTO.getMessage());
//        }
        Map<Integer, List<FaultImageDRO>> faultImageMap = Maps.newHashMap();
        if (CollectionUtil.isNotNullOrEmpty(imageResponseDTO.getData())) {
            imageResponseDTO.getData().forEach(image -> {
                image.getFaultRelevance().forEach(fault -> {
                    List<FaultImageDRO> imageList = faultImageMap.get(fault.getValue());
                    if (CollectionUtil.isNullOrEmpty(imageList)) {
                        imageList = Lists.newArrayList();
                        faultImageMap.put(fault.getValue(), imageList);
                    }
                    imageList.add(image);
                });
            });
        }

        // 处理故障信息 - 处理服务项目数据
        ResponseDTO<List<FaultDRO>> responseDTO = faultListRemoteService.listByIds(checkReportDIO.getFaultIdList());
        log.info("计价器工单报价获取故障：入参：{} 出参：{}", JSON.toJSONString(checkReportDIO.getFaultIdList()), JSON.toJSONString(responseDTO));

        List<OrderFault> orderFaultList = Lists.newArrayListWithCapacity(checkReportDIO.getFaultIdList().size());
        responseDTO.getData().forEach(fault -> {
            if (Objects.equals(fault.getStatus(), GlobalConsts.NO)) {
                return;
            }
            if (!checkReportDIO.getFaultIdList().contains(fault.getFaultId())) {
                return;
            }
            OrderFault orderFault = BeanMapper.map(fault, OrderFault.class);
            orderFault.setOrderId(checkReportDIO.getOrderId());
            orderFault.setCreater(checkReportDIO.getOperator());
            orderFault.setCreateTime(now);

            // 处理服务项名称
            List<ItemDRO> itemList = faultServiceItemMap.get(fault.getFaultId());
            if (CollectionUtil.isNotNullOrEmpty(itemList)) {
                String serviceItemName = itemList.stream().map(ItemDRO::getItemName).collect(Collectors.joining(","));
                // 处理维修难度
                Integer faultDiffculty = itemList.stream().map(itemDRO -> {
                            if (Objects.isNull(itemDRO.getMaintainDifficulty())){
                                return 1;
                            }else {
                                return itemDRO.getMaintainDifficulty();
                            }
                        }).max(Integer::compareTo).get();

                orderFault.setServiceItemName(serviceItemName);
                orderFault.setFaultDifficulty(faultDiffculty);
            }

            // 处理图片数据
            List<FaultImageDRO> imageDROList = faultImageMap.get(fault.getFaultId());
            if (CollectionUtil.isNotNullOrEmpty(imageDROList)) {
                orderFault.setImgInfo(JSON.toJSONString(imageDROList));
            }

            orderFaultList.add(orderFault);
        });

        if (CollectionUtil.isNotNullOrEmpty(orderFaultList)) {
            orderFaultService.insertList(orderFaultList);
        }

        // 处理服务内容
        MeterContentQuery query3 = new MeterContentQuery();
        query3.setChannelId(orderWork.getChannelId());
        query3.setBizType(orderWork.getBizType());
        query3.setErpProductId(orderWork.getProductId());
        query3.setTariffId(orderProduct.getTariffId());
        query3.setItemList(checkReportDIO.getItemList());
        ResponseDTO<List<ServiceContentDRO>> serviceContentResponseDTO = meterFlow3RemoteService.listServiceContentByQuery(query3);
        log.info("计价器工单报价获取服务内容：入参：{} 出参：{}", JSON.toJSONString(query3), JSON.toJSONString(serviceContentResponseDTO));
        if (!serviceContentResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(serviceContentResponseDTO.getData())) {
            throw new OmsBaseException(OmsErrorCodeConsts.CALL_THIRED_SYS_FAILED, serviceContentResponseDTO.getMessage());
        }
        List<ServiceContentDRO> serviceContentDROList = serviceContentResponseDTO.getData();
        List<OrderServiceContent> orderServiceContentList = Lists.newArrayListWithCapacity(serviceContentDROList.size());
        serviceContentDROList.forEach(orderServiceContentDRO -> {
            if (Objects.equals(orderServiceContentDRO.getStatus(), GlobalConsts.NO)) {
                return;
            }
            OrderServiceContent orderServiceContent = BeanMapper.map(orderServiceContentDRO, OrderServiceContent.class);
            orderServiceContent.setOrderId(checkReportDIO.getOrderId());
            orderServiceContent.setServName(orderServiceContentDRO.getServDesc());
            orderServiceContent.setCreater(checkReportDIO.getOperator());
            orderServiceContent.setUpdater(checkReportDIO.getOperator());
            orderServiceContent.setCreateTime(now);
            orderServiceContent.setUpdateTime(now);

            orderServiceContentList.add(orderServiceContent);
        });

        orderServiceContentService.batchInsert(orderServiceContentList);

        // 更新底图
        OrderQuotationProcess updateProcess = new OrderQuotationProcess();
        updateProcess.setOrderId(checkReportDIO.getOrderId());
        updateProcess.setReportSubmitStatus(GlobalConsts.YES);
        if (CollectionUtil.isNotNullOrEmpty(imageResponseDTO.getData())) {
            updateProcess.setBaseImage(imageResponseDTO.getData().get(0).getDefaultImg());
        }

        updateProcess.setPushReportStatus(GlobalConsts.NO);
        updateProcess.setReportConfirmStatus(GlobalConsts.NO);
        updateProcess.setAgreeStatus(GlobalConsts.NONE);

        if (Objects.equals(dbProcess.getReportSubmitStatus(), GlobalConsts.YES)) {
            updateProcess.setEditStatus(GlobalConsts.YES);
            checkReportDIO.setEditStatus(GlobalConsts.YES);
        }

        orderQuotationProcessService.updateByOrderIdSelective(updateProcess);

        // 生成价格
        OrderServiceItem serviceItem = this.generateOrderAmount(checkReportDIO, orderWork, checkReportDIO.getItemList());

        // 处理日志信息
        String faultNameStr = orderFaultList.stream().map(OrderFault::getFaultName).collect(Collectors.joining("、"));
        checkReportDIO.setFaultNameStr(faultNameStr);
    }

    public OrderServiceItem generateOrderAmount(OmsOperator operator, OrderWork orderWork, List<Integer> itemIdList) throws OmsBaseException {
        if (Objects.isNull(orderWork)) {
            orderWork = orderWorkService.findOrderWorkByKey(operator.getOrderId(), operator.getWorkId());
            if (orderWork == null) {
                return null;
            }
        }

        //TODO 已确认，计算价格并记录日志
        List<OrderProductExtend> extendList = orderProductExtendService.listByOrderId(operator.getOrderId());

        Long proExtId = extendList.get(0).getProExtId();

        AddOrderServiceItemDTO addOrderServiceItemDTO = new AddOrderServiceItemDTO();
        addOrderServiceItemDTO.setOrderId(operator.getOrderId());
        addOrderServiceItemDTO.setWorkId(operator.getWorkId());
        addOrderServiceItemDTO.setProExtId(proExtId);
        addOrderServiceItemDTO.setQuotationType(operator.getOperatorType());
        addOrderServiceItemDTO.setIsProductChanged(false);
        addOrderServiceItemDTO.setServItemType(OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE);

        OrderProduct orderProduct = orderProductService.listOrderProductByOrderId(operator.getOrderId()).get(0);
        List<Integer> serviceItemIdList;
        if (CollectionUtil.isNullOrEmpty(itemIdList)) {
            List<OrderQuotationServiceItem> quotationServiceItemList = orderquotationserviceitemService.listByOrderId(operator.getOrderId());

            if (CollectionUtil.isNullOrEmpty(quotationServiceItemList)) {
                throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "无报价服务项");
            }
            serviceItemIdList = quotationServiceItemList.stream().map(OrderQuotationServiceItem::getItemId).collect(Collectors.toList());
        } else {
            serviceItemIdList = itemIdList;
        }

        // 处理服务项
        ItemQuoteQuery quoteQuery3 = ItemQuoteQuery.builder()
                .bizType(orderWork.getBizType())
                .channelId(orderWork.getChannelId())
                .cityId(orderWork.getCityId())
                .productId(orderWork.getProductId())
                .brandId(orderProduct.getBrandId())
                .tariffId(orderProduct.getTariffId())
                .itemList(serviceItemIdList).build();
        ResponseDTO<List<ItemDRO>> itemResponseDTO = itemPriceRemoteService.listItemQuoteByQuery(quoteQuery3);
        log.info("计价器工单确认检测报告获取服务项：入参：{} 出参：{}", JSON.toJSONString(quoteQuery3), JSON.toJSONString(itemResponseDTO));
        if (!itemResponseDTO.isSuccess() || CollectionUtil.isNullOrEmpty(itemResponseDTO.getData())) {
            throw new OmsBaseException(OmsErrorCodeConsts.CALL_THIRED_SYS_FAILED, itemResponseDTO.getMessage());
        }
        List<ItemDRO> itemDRO3List = itemResponseDTO.getData();
        ItemDRO item = itemDRO3List.stream().max(Comparator.comparing(ItemDRO::getPrice)).get();

        OrderServiceItem serviceItem = new OrderServiceItem();
        serviceItem.setServItemId(item.getItemId());
        serviceItem.setServItemName(item.getItemName());
        serviceItem.setInternalSettlementPrice(item.getPriceInternalSettlement());
        serviceItem.setInternalTotalPrice(item.getPriceInternalSettlement());
        serviceItem.setExternalSettlementPrice(item.getPriceExternalSettlement());
        serviceItem.setExternalTotalPrice(item.getPriceExternalSettlement());
        serviceItem.setItemPrice(item.getPrice());
        serviceItem.setTotalPrice(item.getPrice());
        serviceItem.setProductId(orderProduct.getProductId());
        serviceItem.setProductName(orderProduct.getProductName());
        serviceItem.setOrderId(operator.getOrderId());
        serviceItem.setNumber(1);
        serviceItem.setProExtId(proExtId);
        serviceItem.setServItemGroupId(item.getItemTypeId());
        serviceItem.setServItemGroupName(Optional.ofNullable(item.getItemTypeName()).orElse("默认值"));
        serviceItem.setServItemCategId(item.getItemTypeId());
        serviceItem.setTieredTotalPrice(item.getPrice());
        serviceItem.setOrigItemPrice(item.getPrice());
        serviceItem.setOrigTotalPrice(item.getPrice());
        serviceItem.setCreater(operator.getOperator());
        serviceItem.setCreateTime(DateUtil.getNow());


        if (CollectionUtil.isNotNullOrEmpty(item.getItemCellList())) {
            List<OrderServiceItemCell> itemCellList = new ArrayList<>(item.getItemCellList().size());
            for (ItemCellDRO itemCell : item.getItemCellList()) {
                OrderServiceItemCell cell = new OrderServiceItemCell();
                cell.setItemCellId(itemCell.getItemCellId());
                cell.setItemCellName(itemCell.getItemCellName());
                cell.setCellPrice(itemCell.getCellPrice());
                cell.setSort(itemCell.getSort());
                cell.setCreater(operator.getOperator());
                cell.setCreateTime(DateUtil.getNow());
                itemCellList.add(cell);
            }
            serviceItem.setItemDetailList(itemCellList);
        }
        addOrderServiceItemDTO.setOrderServiceItemList(Lists.newArrayList(serviceItem));
        zsMasterWorkBService.updateServiceItem(addOrderServiceItemDTO);

        return serviceItem;
    }

    /**
     * 生成上门费
     * @param operator
     * @param orderWork
     * @throws OmsBaseException
     */
    public void generateVisitServiceItem(OmsOperator operator, OrderWork orderWork) throws OmsBaseException {

        if (Objects.isNull(orderWork)) {
            orderWork = orderWorkService.findOrderWorkByKey(operator.getOrderId(), operator.getWorkId());
            if (orderWork == null) {
                return;
            }
        }

        // 不同意维修，塞上门费
        List<OrderProductExtend> extendList = orderProductExtendService.listByOrderId(operator.getOrderId());

        Long proExtId = extendList.get(0).getProExtId();

        AddOrderServiceItemDTO addOrderServiceItemDTO = new AddOrderServiceItemDTO();
        addOrderServiceItemDTO.setOrderId(operator.getOrderId());
        addOrderServiceItemDTO.setWorkId(operator.getWorkId());
        addOrderServiceItemDTO.setProExtId(proExtId);
        addOrderServiceItemDTO.setQuotationType(operator.getOperatorType());
        addOrderServiceItemDTO.setIsProductChanged(false);
        addOrderServiceItemDTO.setServItemType(OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE);

        OrderProduct orderProduct = orderProductService.listOrderProductByOrderId(operator.getOrderId()).get(0);

        // 处理服务项
        ResponseDTO<ItemAdditionDRO> itemResponseDTO = itemAdditionRemoteService.getDoorFee();
        log.info("计价器工单不同意维修 获取上门费服务项 出参：{}", JSON.toJSONString(itemResponseDTO));
        if (!itemResponseDTO.isSuccess()) {
            throw new OmsBaseException(OmsErrorCodeConsts.CALL_THIRED_SYS_FAILED, itemResponseDTO.getMessage());
        }
        if (Objects.isNull(itemResponseDTO.getData())) {
            // 查不到上门服务项，清空价格
            // 计价器类型变化，清空服务项
            orderServiceItemService.deleteByOrderId(orderWork.getOrderId());
            // 计算和更新工单金额
            ReCalcOrderAmountDIO calcOrderAmountDIO = orderAmountCalcBService.getReCalcOrderAmountDIO(orderWork);
            calcOrderAmountDIO.getOrderAmountDIO().setOriginalAmount(null);
            OrderAmountCalcBO orderAmountCalcBO = orderAmountCalcBService.reCalcOrderAmountAndDiscountAmount(TriggerAmountChangeEnum.DELETE_ORDER_AMOUNT, calcOrderAmountDIO, null);
            orderWorkAmountBService.updateAmountAndDiscount(orderAmountCalcBO,orderWork);
        } else {
            ItemAdditionDRO item = itemResponseDTO.getData();

            OrderServiceItem serviceItem = new OrderServiceItem();
            serviceItem.setServItemId(item.getItemAdditionId());
            serviceItem.setServItemName(item.getItemAdditionName());
            serviceItem.setInternalSettlementPrice(item.getPrice());
            serviceItem.setInternalTotalPrice(item.getPrice());
            serviceItem.setExternalSettlementPrice(item.getPrice());
            serviceItem.setExternalTotalPrice(item.getPrice());
            serviceItem.setItemPrice(item.getPrice());
            serviceItem.setTotalPrice(item.getPrice());
            serviceItem.setProductId(orderProduct.getProductId());
            serviceItem.setProductName(orderProduct.getProductName());
            serviceItem.setOrderId(operator.getOrderId());
            serviceItem.setNumber(1);
            serviceItem.setProExtId(proExtId);
            serviceItem.setServItemGroupId(ItemAdditionConst.ADDITION_DOOR_ID);
            serviceItem.setServItemGroupName(ServiceItemTypeEnum.ADDITION_ITEM.getName());
            // TODO wyc 一口价不同意维修 erp算账需要传 收费服务项的类型id
            serviceItem.setServItemCategId(ItemAdditionConst.ADDITION_DOOR_ID);
            serviceItem.setTieredTotalPrice(item.getPrice());
            serviceItem.setOrigItemPrice(item.getPrice());
            serviceItem.setOrigTotalPrice(item.getPrice());
            serviceItem.setCreater(operator.getOperator());
            serviceItem.setCreateTime(DateUtil.getNow());

//            zsMasterWorkBService.updateServiceItem(addOrderServiceItemDTO);

            // 删除优惠
            ReCalcOrderAmountDIO delCalcOrderAmountDIO = orderAmountCalcBService.getReCalcOrderAmountDIO(orderWork);
            OrderAmountCalcBO delOrderAmountCalcBO = orderAmountCalcBService.reCalcOrderAmountAndDiscountAmount(TriggerAmountChangeEnum.DELETE_ORDER_AMOUNT, delCalcOrderAmountDIO, null);
            orderWorkAmountBService.updateAmountAndDiscount(delOrderAmountCalcBO, orderWork);

            // 删除所有服务项
            orderServiceItemService.deleteByProExtId(proExtId);
            // 插入上门服务项
            orderServiceItemService.insertAll(Lists.newArrayList(serviceItem));

            //保存报价人信息
            OrderOperation orderOperation = new OrderOperation();
            orderOperation.setOrderId(addOrderServiceItemDTO.getOrderId());
            orderOperation.setQuotationId(addOrderServiceItemDTO.getOperatorId() == null ? 0L : addOrderServiceItemDTO.getOperatorId());
            orderOperation.setQuotationType(addOrderServiceItemDTO.getQuotationType() == null ?
                    GlobalConsts.OPERATE_USER_TYPE_SYSTEM : addOrderServiceItemDTO.getQuotationType());
            orderOperation.setQuotationName(addOrderServiceItemDTO.getOperator() == null ? "系统" : addOrderServiceItemDTO.getOperator());
            orderOperation.setCreater(addOrderServiceItemDTO.getOperator() == null ? "系统" : addOrderServiceItemDTO.getOperator());
            Date currentTime = DateUtil.getNow();
            orderOperation.setQuotationTime(currentTime);
            orderOperation.setCreateTime(currentTime);
            orderOperationBService.insertOrUpdateByKey(orderOperation);
            // 重新计算价格
            OrderWork newOrderWork = orderWorkService.findOrderWorkByKeySrcMaster(operator.getOrderId(), operator.getWorkId());
            Integer totalOriginalAmount = item.getPrice();
            ReCalcOrderAmountDIO calcOrderAmountDIO = orderAmountCalcBService.getReCalcOrderAmountDIO(newOrderWork);
            calcOrderAmountDIO.setNewOriginalAmount(totalOriginalAmount);
            calcOrderAmountDIO.setOnlyVisit(GlobalConsts.YES);
            OrderAmountCalcBO orderAmountCalcBO = orderAmountCalcBService.reCalcOrderAmountAndDiscountAmount(TriggerAmountChangeEnum.MODIFY_ORDER_AMOUNT, calcOrderAmountDIO, null);
            orderWorkAmountBService.updateAmountAndDiscount(orderAmountCalcBO, newOrderWork);

            // 清空保修项目
            orderWarrantyService.deleteByOrderId(operator.getOrderId());
        }
    }

    /**
     *
     * @param orderId
     * @param workId
     * @param isDeepClean
     * @throws OmsBaseException
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void clearQuotationInfo(Long orderId, Long workId, boolean isDeepClean) throws OmsBaseException {
        log.info("[{}]清空计价器3.0报价数据, 是否深度清理:{}", orderId, isDeepClean);

        if (isDeepClean) {
            // 清空报价流程信息
            orderQuotationProcessService.deleteByOrderId(orderId);

            // 清空故障现象信息
            orderFaultPhenomenonService.deleteByOrderId(orderId);
        }

        // 清空检测项目
        orderMaintainItemService.deleteByOrderId(orderId);

        // 清空故障信息
        orderFaultService.deleteByOrderId(orderId);

        // 清空服务项目
        orderquotationserviceitemService.deleteByOrderId(orderId);

        // 清空服务内容
        orderServiceContentService.deleteByOrderId(orderId);

        // 清空保修信息
        zsOrderWarrantyBService.deleteWarranty(orderId);
    }

    /**
     *
     * @param orderId
     * @param workId
     * @throws OmsBaseException
     */
    private void resetQuotationInfo(Long orderId, Long workId) throws OmsBaseException {
        this.clearQuotationInfo(orderId, workId, false);

        // 恢复
        OrderQuotationProcess process = orderQuotationProcessService.findByOrderId(orderId);
        if (Objects.equals(process.getReportSubmitStatus(), GlobalConsts.YES)) {
            OrderQuotationProcess updateProcess = new OrderQuotationProcess();
            updateProcess.setOrderId(orderId);
            updateProcess.setReportSubmitStatus(GlobalConsts.YES);
            updateProcess.setFaultCode(null);
            updateProcess.setFaultCodeId(null);
            updateProcess.setUpdateTime(DateUtil.getNow());
            orderQuotationProcessService.updateUnSubmitStatusByOrderId(updateProcess);
        }
    }

    @Override
    //TODO 记录日志
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_PROCESS_CHECK_REPORT, beforeProceed = false)
    public void confirmCheckReportByEngineer(ConfirmCheckReportDIO confirmCheckReportDIO) throws OmsBaseException {
        // 生成订单价格
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(confirmCheckReportDIO.getOrderId(), confirmCheckReportDIO.getWorkId());
        this.commonVerify(orderWork);

        // 判断产品是否修改
        List<OrderMaintainItem> maintainItemList = orderMaintainItemService.listByOrderId(confirmCheckReportDIO.getOrderId());
        if (CollectionUtil.isNullOrEmpty(maintainItemList)) {
            throw new OmsBaseException(OmsErrorCodeConsts.PRODUCT_CHANGED, "服务项目已更改，请重新提交检测报告");
        }

        OrderQuotationProcess process = orderQuotationProcessService.findByOrderIdSrcMaster(confirmCheckReportDIO.getOrderId());

        // 是否已提交检测报告
        if (Objects.isNull(process) || !Objects.equals(process.getReportSubmitStatus(), GlobalConsts.YES)) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "订单已被修改，请重新提交检测报告");
        }

        // 记录检测报告确认状态
        OrderQuotationProcess updateProcess = orderQuotationProcessService.findByOrderId(confirmCheckReportDIO.getOrderId());
        updateProcess.setOrderId(confirmCheckReportDIO.getOrderId());
        updateProcess.setPushReportStatus(GlobalConsts.NO);
        updateProcess.setReportConfirmStatus(GlobalConsts.YES);

        if (Objects.equals(confirmCheckReportDIO.getIsSendCheckReportToUser(), GlobalConsts.YES)) {
            // 是否扫码
            Long visitUserId = orderWork.getVisitUserId();
            if (NumberUtil.isNullOrZero(visitUserId)) {
                throw new OmsBaseException(OmsErrorCodeConsts.ERROR_WECHAT_NO_ATTENTION_CODE, "用户未扫码，不可推送信息");
            }

            // 检验用户是否关注
            checkAttentionWeChat(orderWork);

            log.info("订单[{}]发送微信模板消息-----开始", confirmCheckReportDIO.getOrderId());
            boolean sendResult = messageWeChatTemplateService.sendDesignatedOpenIdWeChatTemplate(confirmCheckReportDIO.getOrderId(), MessageConsts.ZMN_MSG_RULEID_CONFIRM_CHECK_REPORT, visitUserId, null);
            log.info("订单[{}]发送微信模板消息-----结束", confirmCheckReportDIO.getOrderId());
            if (!sendResult) {
                throw new OmsBaseException(OmsErrorCodeConsts.CALL_THIRED_SYS_FAILED, "发送信息失败，请稍后重试");
            }
            // 更新发送状态
            updateProcess.setPushReportStatus(GlobalConsts.YES);
        }
        // 更新
        orderQuotationProcessService.updateByOrderIdSelective(updateProcess);

        confirmCheckReportDIO.setEditStatus(process.getEditStatus());
    }



    @Override
    public void submitConfirmRepairResultByEngineer(ConfirmRepairDIO confirmRepairDIO) throws OmsBaseException {

        OrderLog orderLog = new OrderLog();
        OrderWork orderWork = orderWorkService.findMasterWorkDetail(confirmRepairDIO.getOrderId(), confirmRepairDIO.getWorkId(), confirmRepairDIO.getMasterId());

        if (orderWork == null) {
            throw new OmsBaseException("无效的工单");
        }

        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            throw new OmsBaseException("工单不在进行中");
        }

        orderLog.setType(OrderLogConsts.ORDER_LOG_TYPE_CLICK_CHECK_REPORT);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(orderLog.getType()));
        OrderWorkLogUtils.processOrderLogOperater(orderLog, confirmRepairDIO);
        orderLog.setOperatorTypeName(GlobalConsts.getOperatorTypeName(orderLog.getOperatorType()));
        OrderWorkLogUtils.processOrderLogStatus(orderLog, orderWork, confirmRepairDIO);

        orderLogBService.save(orderLog);

        // 发送订单标签mq
        orderTagBService.sendOrderTagMq(orderWork.getOrderId(), orderWork.getWorkId(), orderLog.getType());
    }


    @Override
    //TODO 记录日志
    public void sendCaptcha(SendAgreeCapthaDIO sendAgreeCapthaDIO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(sendAgreeCapthaDIO.getOrderId(), sendAgreeCapthaDIO.getWorkId());
        this.commonVerify(orderWork);

        OrderQuotationProcess process = orderQuotationProcessService.findByOrderId(sendAgreeCapthaDIO.getOrderId());

        // 是否已提交检测报告
        if (Objects.isNull(process) || !Objects.equals(process.getReportConfirmStatus(), GlobalConsts.YES)) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "订单已被修改，请退出重新确认检测报告");
        }

        log.info("发送验证码给用户：{}", JSON.toJSONString(sendAgreeCapthaDIO));

        // 处理手机号，判断是给下单用户发送还是现场用户
        String mobile ;
        if (Objects.equals(sendAgreeCapthaDIO.getMobileUserType(), GlobalConsts.NO)) {
            OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(sendAgreeCapthaDIO.getOrderId());
            mobile = orderDetail.getTelephone();
        } else {
            mobile = sendAgreeCapthaDIO.getMobile();
        }

        String orderId = sendAgreeCapthaDIO.getOrderId().toString();
        Integer masterId = sendAgreeCapthaDIO.getOperatorId().intValue();
        String captcha;
        Map<String, String> map = Maps.newHashMap();

        orderWorkCaptchaBService.validateUserPhoneNum(mobile, masterId);

        String limitKey = String.format(RedisKeyConsts.ORDER_AGREE_REPAIR_TIME, mobile);
        String incrStr = redisManager.get(limitKey);
        // 工程师半小时内十条短信限制
        if (StringUtils.isNotBlank(incrStr) && Integer.parseInt(incrStr) >= MOBILE_SEND_AGREE_REPAIR_LIMIT) {
            throw new OmsBaseException("该手机号本月发送短信次数已达上限");
        }

        //一分钟内相同验证码逻辑
        String oneMinKey = String.format(RedisKeyConsts.ORDER_CAPTCHA_SEND_LIMIT1_KEY, orderId);
        String value = redisManager.get(oneMinKey);
        if (value != null) {
            captcha = value;
        } else {
            captcha = StringUtil.getRandomsNumber(6);
            String fifteenMinKey = String.format(RedisKeyConsts.ORDER_CAPTCHA_SEND_LIMIT15_KEY, orderId);
            redisManager.setex(fifteenMinKey, captcha, 15 * 60);
            redisManager.setex(oneMinKey, captcha, 60);
        }

        map.put("code", captcha);

        SmsMessageDTO smsMessageDTO = SmsMessageDTO.builder()
                .orderId(sendAgreeCapthaDIO.getOrderId())
                .businessId(sendAgreeCapthaDIO.getOrderId())
                .ruleId(MessageConsts.ZMN_MSG_RULEID_AGREE_REPAIR)
                .mobile(mobile)
                .channelId(String.valueOf(orderWork.getChannelId()))
                .cityId(String.valueOf(orderWork.getCityId()))
                .params(JSON.toJSONString(map))
                .build();

        boolean isSuccess = messageSendBaseService.sendTextMessage(smsMessageDTO);
        if (!isSuccess) {
            throw new OmsBaseException("发送短信失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_AGREE_REPAIR_RESULT)
    public void submitConfirmRepairResult(ConfirmRepairDIO confirmRepairDIO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(confirmRepairDIO.getOrderId(), confirmRepairDIO.getWorkId());
        this.commonVerify(orderWork);

        OrderQuotationProcess dbProcess = orderQuotationProcessService.findByOrderId(confirmRepairDIO.getOrderId());

        // 是否已确认检测报告
        if (Objects.isNull(dbProcess) || !Objects.equals(dbProcess.getReportConfirmStatus(), GlobalConsts.YES)) {
            if (Objects.equals(confirmRepairDIO.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_MASTER)) {
                throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "订单已被修改，请退出重新确认检测报告");
            } else {
                throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "订单已被修改，请提醒工程师重新确认检测报告");
            }
        }

        OrderQuotationProcess updateProcess = new OrderQuotationProcess();
        updateProcess.setOrderId(confirmRepairDIO.getOrderId());
        updateProcess.setAgreeStatus(confirmRepairDIO.getResult());
        updateProcess.setAgreeTime(DateUtil.getNow());
        updateProcess.setAgreeOperatorId(confirmRepairDIO.getOperatorId());
        updateProcess.setAgreeOperatorType(confirmRepairDIO.getOperatorType());
        updateProcess.setUpdater(confirmRepairDIO.getOperator());
        updateProcess.setUpdateTime(DateUtil.getNow());
        orderQuotationProcessService.updateByOrderIdSelective(updateProcess);

        // 如果是修改是否同意维修
        if (NumberUtil.isNotNullOrZero(dbProcess.getAgreeStatus())) {
            // 删除人工优惠
            if (NumberUtil.isNotNullOrZero(dbProcess.getEngineerDiscountId()) && Objects.equals(dbProcess.getEngineerDiscountStatus(), GlobalConsts.YES)) {
                // 删除人工优惠
                ReCalcOrderAmountDIO calcOrderAmountDIO = orderAmountCalcBService.getReCalcOrderAmountDIO(orderWork);
                // 计算和更新工单金额
                OrderAmountCalcBO orderAmountCalcBO = orderAmountCalcBService.reCalcOrderAmountAndDiscountAmount(TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT_DELETE, calcOrderAmountDIO, null);
                orderWorkAmountBService.updateAmountAndDiscount(orderAmountCalcBO, orderWork);
            }
        }

        if (Objects.equals(confirmRepairDIO.getResult(), GlobalConsts.NO)) {
            this.generateVisitServiceItem(confirmRepairDIO, null);
        } else {
            // 如果是不同意->确认 重新生成服务项
            this.generateOrderAmount(confirmRepairDIO, null, null);
        }

        // 如果是不同意改为同意，之前领取的人工优惠再次使用

        if (NumberUtil.isNotNullOrZero(dbProcess.getEngineerDiscountId()) && Objects.equals(confirmRepairDIO.getResult(), GlobalConsts.YES)
                && Objects.equals(dbProcess.getEngineerDiscountStatus(), GlobalConsts.YES)) {
            if (NumberUtil.isNotNullOrZero(dbProcess.getEngineerDiscountAmount())){
                // 保存人工优惠
                ZsDiscountDTO zsDiscountDTO = new ZsDiscountDTO();
                zsDiscountDTO.setOrderId(confirmRepairDIO.getOrderId());
                zsDiscountDTO.setWorkId(confirmRepairDIO.getWorkId());
                zsDiscountDTO.setOperateId(GlobalConsts.NONE);
                zsDiscountDTO.setOperatorId(confirmRepairDIO.getOperatorId());
                zsDiscountDTO.setOperatorType(confirmRepairDIO.getOperatorType());
                zsDiscountDTO.setOperator(confirmRepairDIO.getOperator());
                zsDiscountDTO.setDiscountAmount(dbProcess.getEngineerDiscountAmount());
                zsNormalOrderDiscountBService.saveDiscount(zsDiscountDTO, TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT);
            }else{
                // 使用优惠
                ZsDiscountDTO discountDTO = new ZsDiscountDTO();
                discountDTO.setOrderId(confirmRepairDIO.getOrderId());
                discountDTO.setWorkId(confirmRepairDIO.getWorkId());
                discountDTO.setMasterDiscountId(dbProcess.getEngineerDiscountId());
                discountDTO.setOperatorId(confirmRepairDIO.getOperatorId());
                discountDTO.setOperator(confirmRepairDIO.getOperator());
                discountDTO.setOperatorType(confirmRepairDIO.getOperatorType());
                zsNormalOrderDiscountBService.saveDiscount(discountDTO, TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT_PROM);
            }

        }

        // 如果是用户操作同意维修
        if (Objects.equals(confirmRepairDIO.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_USER) && Objects.equals(confirmRepairDIO.getResult(), GlobalConsts.YES)) {
            this.sendUserAgreeInfo(orderWork);
        }
    }

    @Override
    //TODO 记录日志
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_AGREE_REPAIR_RESULT_WITH_CAPTCHA)
    public void submitConfirmRepairResultWithCaptcha(ConfirmRepairDIO confirmRepairDIO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(confirmRepairDIO.getOrderId(), confirmRepairDIO.getWorkId());
        this.commonVerify(orderWork);

        OrderQuotationProcess dbProcess = orderQuotationProcessService.findByOrderId(confirmRepairDIO.getOrderId());

        // 是否已确认检测报告
        if (Objects.isNull(dbProcess) || !Objects.equals(dbProcess.getReportConfirmStatus(), GlobalConsts.YES)) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "订单已被修改，请重新确认检测报告");
        }

        if (Objects.equals(confirmRepairDIO.getResult(), GlobalConsts.YES) && Objects.equals(confirmRepairDIO.getOperatorType(), GlobalConsts.OPERATE_USER_TYPE_MASTER)) {
            // 处理手机号，判断是给下单用户发送还是现场用户
            String mobile ;
            if (Objects.equals(confirmRepairDIO.getMobileUserType(), GlobalConsts.NO)) {
                OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(confirmRepairDIO.getOrderId());
                mobile = orderDetail.getTelephone();
            } else {
                mobile = confirmRepairDIO.getMobile();
            }

            if (StringUtils.isBlank(confirmRepairDIO.getCaptcha())) {
                throw new OmsBaseException(OmsErrorCodeConsts.PARAMS_VERIFY_EXCEPTION, "工程师操作同意维修验证码不能为空");
            }
            // 判断验证码是否正确
            String redisCaptcha = redisManager.get(String.format(RedisKeyConsts.ORDER_CAPTCHA_SEND_LIMIT15_KEY, confirmRepairDIO.getOrderId()));
            if (redisCaptcha == null || !Objects.equals(redisCaptcha, confirmRepairDIO.getCaptcha())) {
                log.info("validateVerificationCode#校验验错误：{} 入参：{}", redisCaptcha, JSON.toJSONString(confirmRepairDIO));
                throw new OmsBaseException("确认码错误");
            }
            // 验证通过后，双删验证码。
            redisManager.del(RedisKeyConsts.ORDER_CAPTCHA_SEND_LIMIT1_KEY, RedisKeyConsts.ORDER_CAPTCHA_SEND_LIMIT15_KEY);

            // 计数
            String limitKey = String.format(RedisKeyConsts.ORDER_AGREE_REPAIR_TIME, mobile);
            if (!redisManager.exists(limitKey)) {
                // 离散该数据，推迟至12点后的一小时内，防止大量过期导致redis阻塞
                redisManager.incr(limitKey);
                int offset = new Random().nextInt(3600);
                Long deffer = DateTimeUtil.getMonthLastDayDeffer(DateUtil.getNow()) + offset;
                redisManager.expire(limitKey, deffer.intValue());
            } else {
                redisManager.incr(limitKey);
            }
        }

        // 如果是修改是否同意维修
        if (NumberUtil.isNotNullOrZero(dbProcess.getAgreeStatus())) {
            // 删除人工优惠
            this.clearEngineerDiscount(orderWork, false);
        }

        OrderQuotationProcess updateProcess = new OrderQuotationProcess();
        updateProcess.setOrderId(confirmRepairDIO.getOrderId());
        updateProcess.setAgreeStatus(confirmRepairDIO.getResult());
        updateProcess.setAgreeTime(DateUtil.getNow());
        updateProcess.setAgreeOperatorId(confirmRepairDIO.getOperatorId());
        updateProcess.setAgreeOperatorType(confirmRepairDIO.getOperatorType());
        updateProcess.setUpdater(confirmRepairDIO.getOperator());
        updateProcess.setUpdateTime(DateUtil.getNow());
        orderQuotationProcessService.updateByOrderIdSelective(updateProcess);


        if (Objects.equals(confirmRepairDIO.getResult(), GlobalConsts.NO)) {
            this.generateVisitServiceItem(confirmRepairDIO, null);
        } else if (Objects.equals(dbProcess.getAgreeStatus(), GlobalConsts.NO)){
            // 如果是不同意->确认 重新生成服务项
            this.generateOrderAmount(confirmRepairDIO, null, null);
        }

    }

    @Override
    public void sendFaultConfirmMessage(OmsOperator operator) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(operator.getOrderId(), operator.getWorkId());

        if (NumberUtil.isNullOrZero(orderWork.getVisitUserId())) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "用户未扫码，不可推送信息");
        }

        log.info("订单[{}]发送微信模板消息-----开始", operator.getOrderId());
        boolean sendResult = messageWeChatTemplateService.sendDesignatedOpenIdWeChatTemplate(operator.getOrderId(), MessageConsts.ZMN_MSG_RULEID_USER_FAULT_REPORT, orderWork.getVisitUserId(), null);
        log.info("订单[{}]发送微信模板消息-----结束", operator.getOrderId());
        if (!sendResult) {
            throw new OmsBaseException(OmsErrorCodeConsts.SEND_MESSAGE_FAIL, "发送信息失败，请稍后重试");
        }
    }

    @Override
    public void confirmUserAgreeResultByEngineer(ConfirmRepairDIO confirmRepairDIO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(confirmRepairDIO.getOrderId(), confirmRepairDIO.getWorkId());
        this.commonVerify(orderWork);
        OrderQuotationProcess process = orderQuotationProcessService.findByOrderIdSrcMaster(confirmRepairDIO.getOrderId());

        if (NumberUtil.isNullOrZero(process.getAgreeStatus()) && Objects.equals(confirmRepairDIO.getResult(), GlobalConsts.NO)) {
            orderQuotation3ModifyBService.submitConfirmRepairResult(confirmRepairDIO);
            return;
        }

        if (!Objects.equals(confirmRepairDIO.getResult(), process.getAgreeStatus())) {
            if (Objects.equals(confirmRepairDIO.getResult(), GlobalConsts.YES)) {
                throw new OmsBaseException("请先协助用户确认，再开始维修");
            } else if (Objects.equals(confirmRepairDIO.getResult(), GlobalConsts.NO)) {
                throw new OmsBaseException("用户已同意维修，请点击『开始维修』");
            }
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public String addDiscountByEngineer(EngineerDiscountDIO engineerDiscountDIO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(engineerDiscountDIO.getOrderId(), engineerDiscountDIO.getWorkId());
        this.commonVerify(orderWork);

        OrderQuotationProcess updateProcess = new OrderQuotationProcess();
        updateProcess.setOrderId(engineerDiscountDIO.getOrderId());
        updateProcess.setEngineerDiscountId(engineerDiscountDIO.getPromId());
        updateProcess.setEngineerDiscountStatus(GlobalConsts.NO);
        updateProcess.setUpdater(engineerDiscountDIO.getOperator());
        updateProcess.setUpdateTime(DateUtil.getNow());
        orderQuotationProcessService.updateByOrderIdSelective(updateProcess);

        // 通知DMS
        SendMeter3ArtificialPromDIO dio = new SendMeter3ArtificialPromDIO();
        dio.setOrderId(orderWork.getOrderId());
        dio.setChannelId(orderWork.getChannelId());
        dio.setCityId(orderWork.getCityId());
        dio.setProductId(orderWork.getShowProductId());
        dio.setPromId(engineerDiscountDIO.getPromId());
        dio.setOperator(engineerDiscountDIO.getOperator());
        ResponseDTO responseDTO = meter3ArtificialPromModifyRemoteService.sendMeter3ArtificialProm(dio);
        log.info("调用dms发放工程师优惠券 入参:{}, 出参:{}", JSON.toJSONString(dio), JSON.toJSONString(responseDTO));
        if (!responseDTO.isSuccess()) {
            throw new OmsBaseException(OmsErrorCodeConsts.CALL_THIRED_SYS_FAILED, "调用dms发放工程师优惠失败， 入参:" + JSON.toJSONString(dio));
        }

        return getEngineerDiscountUrl(orderWork.getOrderId());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @ZsNormalOrderWorkLog(type = OrderLogConsts.ORDER_LOG_TYPE_USE_ENGINEER_DISCOUNT)
    public void useEngineerDiscount(EngineerDiscountDIO engineerDiscountDIO) throws OmsBaseException  {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(engineerDiscountDIO.getOrderId(), engineerDiscountDIO.getWorkId());

        if (orderWork == null) {
            throw new OmsBaseException(OmsErrorCodeConsts.ORDER_NOT_FOUND, "订单不存在");
        }
        // 校验
        OrderQuotationProcess dbProcess = orderQuotationProcessService.findByOrderId(engineerDiscountDIO.getOrderId());
        if (Objects.equals(dbProcess.getAgreeStatus(), GlobalConsts.NO)) {
            throw new OmsBaseException("工单不同意维修，不可领取优惠券");
        }
        if (Objects.equals(dbProcess.getEngineerDiscountId(), engineerDiscountDIO.getPromId()) && Objects.equals(dbProcess.getEngineerDiscountStatus(), GlobalConsts.YES)) {
            throw new OmsBaseException("优惠已经领取，不可重复领取");
        }
        if (Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_FAIL)
                || Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DISCARD)) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "优惠已失效");
        }
//        if (!Objects.equals(orderWork.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE)) {
//            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "订单非计价器3.0订单，不可走计价器3.0流程");
//        }
        if (orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_VISIT) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "优惠已失效");
        }
        if (orderWork.getStatus() > OrderStatusConsts.WORK_STATUS_COMPLETE) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "优惠已失效");
        }
        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING)) {
            throw new OmsBaseException("订单已取消，不可领取优惠");
        }
        if (orderWork.getStatus() >= OrderStatusConsts.WORK_STATUS_COMPLETE) {
            throw new OmsBaseException("订单已完成，不可领取优惠");
        }
        if (orderWork.getStatus() <= OrderStatusConsts.WORK_STATUS_DISTRIBUTE) {
            throw new OmsBaseException("订单未派单，不可领取优惠");
        }

        // 先调用dms，以防优惠过期等问题
        ReceiveMeter3ArtificialPromDIO dio = new ReceiveMeter3ArtificialPromDIO();
        dio.setOperator(engineerDiscountDIO.getOperator());
        dio.setOrderId(engineerDiscountDIO.getOrderId());
        dio.setPromId(engineerDiscountDIO.getPromId());
        log.info("调用dms领取优惠接口 入参：{}", JSON.toJSONString(dio));
        ResponseDTO responseDTO = meter3ArtificialPromModifyRemoteService.receiveMeter3ArtificialProm(dio);
        log.info("调用dms领取优惠接口 出参：{}", JSON.toJSONString(responseDTO));
        if (!responseDTO.isSuccess()) {
            throw new OmsBaseException(OmsErrorCodeConsts.CALL_THIRED_SYS_FAILED, responseDTO.getMessage());
        }

        if (NumberUtil.isNotNullOrZero(dbProcess.getEngineerDiscountId())) {
            // 删除人工优惠
            ReCalcOrderAmountDIO calcOrderAmountDIO = orderAmountCalcBService.getReCalcOrderAmountDIO(orderWork);
            // 计算和更新工单金额
            OrderAmountCalcBO orderAmountCalcBO = orderAmountCalcBService.reCalcOrderAmountAndDiscountAmount(TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT_DELETE, calcOrderAmountDIO, null);
            orderWorkAmountBService.updateAmountAndDiscount(orderAmountCalcBO, orderWork);
        }

        // 使用优惠
        ZsDiscountDTO discountDTO = new ZsDiscountDTO();
        discountDTO.setOrderId(engineerDiscountDIO.getOrderId());
        discountDTO.setWorkId(engineerDiscountDIO.getWorkId());
        discountDTO.setMasterDiscountId(engineerDiscountDIO.getPromId());
        discountDTO.setOperatorId(engineerDiscountDIO.getOperatorId());
        discountDTO.setOperator(engineerDiscountDIO.getOperator());
        discountDTO.setOperatorType(engineerDiscountDIO.getOperatorType());
        zsNormalOrderDiscountBService.saveDiscount(discountDTO, TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT_PROM);

        // 更新工程师优惠领取状态
        OrderQuotationProcess process = new OrderQuotationProcess();
        process.setEngineerDiscountStatus(GlobalConsts.YES);
        process.setOrderId(engineerDiscountDIO.getOrderId());
        process.setUpdater(engineerDiscountDIO.getOperator());
        process.setUpdateTime(DateUtil.getNow());

        // 更新金额
//        try (HintManager hintManager = HintManager.getInstance()) {
//            hintManager.setMasterRouteOnly();
//            OrderAmountDRO orderAmountDRO = orderQuotation3ListBService.getOrderAmount(engineerDiscountDIO.getOrderId(), engineerDiscountDIO.getWorkId(), null);
//            process.setAmountJson(JSON.toJSONString(orderAmountDRO));
//        }

        orderQuotationProcessService.updateByOrderIdSelective(process);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void saveDiscount(ArtificialDiscountDIO artificialDiscountDIO) throws OmsBaseException {
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(artificialDiscountDIO.getOrderId(), artificialDiscountDIO.getWorkId());
        if (Objects.equals(artificialDiscountDIO.getDiscountAmount(),0)){
            boolean clearEngineerDiscount = this.clearEngineerDiscount(orderWork, true);
            if (!clearEngineerDiscount){
                throw new OmsBaseException("还没有申请人工优惠，无法取消优惠");
            }

            // 记录日志
            StringBuilder sb = new StringBuilder();
            sb.append("删除优惠金额\n");
            sb.append("app系统：").append(artificialDiscountDIO.getAppPlat().equals(1)?"Android\n":"IOS\n");
            sb.append("版本号：V").append(artificialDiscountDIO.getDisplayVersion());
            this.orderWorkWarrantyAmountLog(orderWork,OrderLogConsts.ORDER_LOG_TYPE_DISCOUNT_ARTIFICIAL_MASTER,sb.toString(),artificialDiscountDIO);
        } else {
            // 判断当前订单是否申请过优惠
            OrderQuotationProcess orderQuotationProcess = orderQuotationProcessService.findByOrderId(artificialDiscountDIO.getOrderId());
            if (!Objects.isNull(orderQuotationProcess) && orderQuotationProcess.getFirstDiscount()){
                ResponseDTO<Boolean> useDiscount = engineerDiscountModifyRemoteService.useDiscount(artificialDiscountDIO.getMasterId(), artificialDiscountDIO.getOrderId() + "");
                log.info("保存人工优惠,减少工程师优惠次数,调用useDiscount，出参:{}",useDiscount);
                if (!useDiscount.isSuccess() || Objects.isNull(useDiscount.getData()) || !useDiscount.getData()){
                    throw new OmsBaseException("您本月的优惠次数已用完，请联系子公司恢复");
                }
            }
            // 保存优惠记录
            OrderQuotationProcess updateProcess = new OrderQuotationProcess();
            updateProcess.setOrderId(artificialDiscountDIO.getOrderId());
            updateProcess.setEngineerDiscountId(artificialDiscountDIO.getPromId());
            updateProcess.setEngineerDiscountStatus(GlobalConsts.YES);
            updateProcess.setUpdater(artificialDiscountDIO.getOperator());
            updateProcess.setUpdateTime(DateUtil.getNow());
            updateProcess.setCreater(artificialDiscountDIO.getOperator());
            updateProcess.setCreateTime(DateUtil.getNow());
            updateProcess.setEngineerDiscountAmount(artificialDiscountDIO.getDiscountAmount());
            updateProcess.setFirstDiscount(false);
            orderQuotationProcessService.updateByOrderIdSelective(updateProcess);

            // 保存人工优惠
            ZsDiscountDTO zsDiscountDTO = new ZsDiscountDTO();
            zsDiscountDTO.setOrderId(artificialDiscountDIO.getOrderId());
            zsDiscountDTO.setWorkId(artificialDiscountDIO.getWorkId());
            zsDiscountDTO.setOperateId(GlobalConsts.NONE);
            zsDiscountDTO.setOperatorId(artificialDiscountDIO.getOperatorId());
            zsDiscountDTO.setOperatorType(artificialDiscountDIO.getOperatorType());
            zsDiscountDTO.setOperator(artificialDiscountDIO.getOperator());
            zsDiscountDTO.setDiscountAmount(artificialDiscountDIO.getDiscountAmount());
            zsNormalOrderDiscountBService.saveDiscount(zsDiscountDTO, TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT);

            // 记录日志
            StringBuilder sb = new StringBuilder();
            sb.append("人工优惠：优惠金额：").append(artificialDiscountDIO.getDiscountAmount() / 100+".00\n");
            sb.append("app系统：").append(artificialDiscountDIO.getAppPlat().equals(1)?"Android\n":"IOS\n");
            sb.append("版本号：V").append(artificialDiscountDIO.getDisplayVersion());
            this.orderWorkWarrantyAmountLog(orderWork,OrderLogConsts.ORDER_LOG_TYPE_DISCOUNT_ARTIFICIAL_MASTER,sb.toString(),artificialDiscountDIO);
        }

    }

    @Override
    public void sendDiscountToUser(MobileDIO mobileDIO) throws OmsBaseException {
        log.info("短信推送活动给用户：{}", JSON.toJSONString(mobileDIO));
        OrderWork orderWork = orderWorkService.findOrderWorkByKey(mobileDIO.getOrderId(), mobileDIO.getWorkId());
        this.commonVerify(orderWork);

        String orderId = mobileDIO.getOrderId().toString();

        // 处理手机号，判断是给下单用户发送还是现场用户
        String mobile ;
        if (Objects.equals(mobileDIO.getMobileUserType(), GlobalConsts.NO)) {
            OrderDetail orderDetail = orderDetailService.findOrderDetailByKey(mobileDIO.getOrderId());
            mobile = orderDetail.getTelephone();
        } else {
            mobile = mobileDIO.getMobile();
        }

        Integer masterId = mobileDIO.getOperatorId().intValue();

        Map<String, String> map = Maps.newHashMap();
        int ruleId = MessageConsts.ZMN_MSG_RULEID_PUST_DISCOUNT;
        orderWorkCaptchaBService.validateUserPhoneNum(mobile, masterId);

//        String limitKey = String.format(RedisKeyConsts.ORDER_AGREE_REPAIR_TIME, mobile);
//        String incrStr = redisManager.get(limitKey);
//        // 工程师半小时内十条短信限制
//        if (StringUtils.isNotBlank(incrStr) && Integer.parseInt(incrStr) >= MOBILE_SEND_AGREE_REPAIR_LIMIT) {
//            throw new OmsBaseException("该手机号本月发送短信次数已达上限");
//        }

        OrderQuotationProcess process = orderQuotationProcessService.findByOrderId(mobileDIO.getOrderId());
        if (NumberUtil.isNullOrZero(process.getEngineerDiscountId())) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "请先选择优惠");
        }

        // 获取工程师优惠活动名称
        Meter3ArtificialPromQuery dio = Meter3ArtificialPromQuery.builder()
                .channelId(orderWork.getChannelId())
                .cityId(orderWork.getCityId())
                .productId(orderWork.getShowProductId())
                .promId(process.getEngineerDiscountId())
                .build();
        ResponseDTO<Meter3ArtificialPromDRO> responseDTO = meter3ArtificialPromListRemoteService.getMeter3ArtificialPromByQuery(dio);
        log.info("获取工程师优惠信息 入参：{} 出参：{}", JSON.toJSONString(dio), JSON.toJSONString(responseDTO));
        if (!responseDTO.isSuccess() || Objects.isNull(responseDTO.getData())) {
            throw new OmsBaseException(OmsErrorCodeConsts.CALL_THIRED_SYS_FAILED, "获取工程师优惠信息失败");
        }
        map.put("activity_name", responseDTO.getData().getShowName());

        ShortLinkDIO shortLinkDIO = new ShortLinkDIO();
        shortLinkDIO.setBussinessId(ruleId);
        // 名字不能重复
        shortLinkDIO.setName(mobileDIO.getOrderId() + "discount:" + DateUtil.toString(DateUtil.getNow()));
        shortLinkDIO.setLink(getEngineerDiscountUrl(mobileDIO.getOrderId()));
        shortLinkDIO.setValidEndTime(DateUtil.addDays(DateUtil.getNow(), 7));
        log.info("订单号【{}】获取工程师优惠getShortLink入参【{}】)", mobileDIO.getOrderId(), shortLinkDIO);
        ResponseDTO<ShortLinkDRO> resp = shortLinkModifyRemoteService.getShortLink(shortLinkDIO);
        log.info("订单号【{}】获取工程师优惠getShortLink出参【{}】)", mobileDIO.getOrderId(), resp);
        if (!resp.isSuccess()) {
            throw new OmsBaseException("获取工程师优惠短连接失败");
        }
        String url = resp.getData().getQrCodeId();
        map.put("short_link", url);

        SmsMessageDTO smsMessageDTO = SmsMessageDTO.builder()
                .orderId(mobileDIO.getOrderId())
                .businessId(mobileDIO.getOrderId())
                .ruleId(ruleId)
                .mobile(mobile)
                .channelId(String.valueOf(orderWork.getChannelId()))
                .cityId(String.valueOf(orderWork.getCityId()))
                .params(JSON.toJSONString(map))
                .build();
        boolean isSuccess = messageSendBaseService.sendTextMessage(smsMessageDTO);
        if (!isSuccess) {
            throw new OmsBaseException("发送优惠活动短信失败");
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addOrderAcceptMaintainItem(AddOrderAcceptMaintainDIO addOrderAcceptMaintainDIO) {

        //先删除旧的验收，再插入新的
        orderAcceptMaintainItemService.deleteByOrderId(addOrderAcceptMaintainDIO.getOrderId());

        // 没有工程师验收项目直接返回
        if (CollectionUtil.isNullOrEmpty(addOrderAcceptMaintainDIO.getOrderAcceptMaintainItemList())) {
            return;
        }

        List<OrderAcceptMaintainItem> orderAcceptMaintainItemList = Lists.newArrayListWithCapacity(addOrderAcceptMaintainDIO.getOrderAcceptMaintainItemList().size());
        addOrderAcceptMaintainDIO.getOrderAcceptMaintainItemList().forEach(item -> {
            OrderAcceptMaintainItem orderAcceptMaintainItem = new OrderAcceptMaintainItem();
            orderAcceptMaintainItem.setOrderId(addOrderAcceptMaintainDIO.getOrderId());
            orderAcceptMaintainItem.setWorkId(addOrderAcceptMaintainDIO.getWorkId());

            orderAcceptMaintainItem.setAcceptMaintainId(item.getAcceptMaintainId());
            orderAcceptMaintainItem.setAcceptMaintainName(item.getAcceptMaintainName());
            orderAcceptMaintainItem.setReferenceName(item.getReferenceName());
            orderAcceptMaintainItem.setSelectedValue(item.getSelectedValue());
            orderAcceptMaintainItem.setSelectedName(item.getSelectedName());
            orderAcceptMaintainItem.setSelectedType(item.getSelectedType());
            orderAcceptMaintainItem.setResult(Optional.ofNullable(item.isStatus()).orElse(false) ? GlobalConsts.YES : GlobalConsts.NO);

            orderAcceptMaintainItem.setCreater(addOrderAcceptMaintainDIO.getOperator());
            orderAcceptMaintainItem.setUpdater(addOrderAcceptMaintainDIO.getOperator());
            orderAcceptMaintainItem.setCreateTime(addOrderAcceptMaintainDIO.getOperateTime());
            orderAcceptMaintainItem.setUpdateTime(addOrderAcceptMaintainDIO.getOperateTime());
            orderAcceptMaintainItemList.add(orderAcceptMaintainItem);
        });
        orderAcceptMaintainItemService.batchInsert(orderAcceptMaintainItemList);
    }

    private String getEngineerDiscountUrl(Long orderId) {
        // 生成二维码
        return  ORDER_MASTER_DISCOUNT_URL + orderId;
    }

    private void commonVerify(OrderWork orderWork) throws OmsBaseException {
        if (orderWork == null) {
            throw new OmsBaseException(OmsErrorCodeConsts.ORDER_NOT_FOUND, "订单不存在");
        }
//        if (!Objects.equals(orderWork.getServItemType(), OrderConsts.SERVICE_ITEM_TYPE_QUOTATION_THREE)) {
//            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "订单非计价器3.0订单，不可走计价器3.0流程");
//        }
        if (orderWork.getStatus() < OrderStatusConsts.WORK_STATUS_VISIT) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "订单未上门，不可操作");
        }
        if (orderWork.getStatus() > OrderStatusConsts.WORK_STATUS_COMPLETE) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "订单已完成，不可操作");
        }
        if (Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_FAIL)
        || Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DISCARD)) {
            throw new OmsBaseException(OmsErrorCodeConsts.STATUS_NOT_LEGAL, "订单已取消，不可操作");
        }
    }

    /**
     * 向app发送验收结果
     *
     * @param orderWork
     * @param orderWork
     */
    private void sendUserAgreeInfo(OrderWork orderWork) {
        // 验收结果发送app push消息
        Map<String, Object> params = Maps.newHashMap();
        params.put("order_id", String.valueOf(orderWork.getOrderId()));
        params.put("work_id", String.valueOf(orderWork.getWorkId()));

        int ruleId = MessageConsts.PUSH_MSG_RULEID_USER_AGREE_REPAIR;

        AppMessageDTO appMessageDTO = new AppMessageDTO();
        appMessageDTO.setOrderId(orderWork.getOrderId());
        appMessageDTO.setChannelId(String.valueOf(orderWork.getChannelId()));
        appMessageDTO.setCityId(String.valueOf(orderWork.getCityId()));
        appMessageDTO.setPlat(orderWork.getPlatWork());
        appMessageDTO.setMasterId(orderWork.getMasterId());
        appMessageDTO.setRuleId(ruleId);
        appMessageDTO.setParams(JSON.toJSONString(params));
        log.info("[{}]用户同意维修结果发送app消息-开始", orderWork.getOrderId());
        Boolean isSuccess = messageSendBaseService.sendAndroidAndIOSMessage(appMessageDTO);
        log.info("[{}]用户同意维修结果发送app消息结果：【{}】-结束", orderWork.getOrderId(), isSuccess);
    }

    // AI 检修方式相关接口
    @Override
    public OperateResultDRO submitFaultCode(SubmitFaultCodeDIO submitFaultCodeDIO) throws OmsBaseException {

        // 清空报价信息
//        this.clearQuotationInfo(submitFaultCodeDIO.getOrderId(), submitFaultCodeDIO.getWorkId(), false);

        OperateResultDRO result = new OperateResultDRO();

        OrderQuotationProcess process = orderQuotationProcessService.findByOrderId(submitFaultCodeDIO.getOrderId());
        if (!Objects.equals(process.getCheckFaultCodeStatus(), GlobalConsts.NO) && Objects.equals(process.getFaultCodeId(), submitFaultCodeDIO.getFaultCodeId())) {
            return new OperateResultDRO(false);
        }

        Date now = DateUtil.getNow();
        // 更新相关数据
        OrderQuotationProcess updateProcess = new OrderQuotationProcess();
        updateProcess.setOrderId(submitFaultCodeDIO.getOrderId());
        updateProcess.setFaultCodeId(submitFaultCodeDIO.getFaultCodeId());
        updateProcess.setFaultCode(submitFaultCodeDIO.getFaultCode());
        updateProcess.setUpdater(submitFaultCodeDIO.getOperator());
        updateProcess.setUpdateTime(now);
        orderQuotationProcessService.updateFaultCodeByOrderId(updateProcess);


        return new OperateResultDRO(true);
    }

    /**
     * 校验配件
     * @param orderWork
     * @param itemIdList
     * @throws OmsBaseException
     */
    private void verifyPart(OrderWork orderWork, List<Integer> itemIdList) throws OmsBaseException {
        if (!Objects.equals(orderWork.getFinalPrice(), GlobalConsts.YES)) {
            return;
        }

        if (NumberUtil.isNullOrZero(orderWork.getPartUse())) {
            throw new OmsBaseException("请选择是否需要使用配件");
        }

        if (CollectionUtil.isNullOrEmpty(itemIdList)) {
            return;
        }

        log.info("serviceItemListRemoteService.getItemPartByItemId serviceItemIdList={}", itemIdList);
        ResponseDTO<List<ItemPartsDRO>> responseDTO = itemPartsRemoteService.listItemPartByItemIds(itemIdList);
        log.info("serviceItemListRemoteService.getItemPartByItemId responseDTO={}", JSON.toJSONString(responseDTO));
        if (!responseDTO.isSuccess()) {
            throw new OmsBaseException(responseDTO.getMessage());
        }

        if (CollectionUtil.isNullOrEmpty(responseDTO.getData())) {
            return;
        }

        // 内采
        boolean notInPart = false;
        SingleMasterOrderPartDTO singleMasterOrderPartDTO = orderPartBService.listByOrderIdAndMaster(orderWork.getOrderId(), orderWork.getMasterId());
        if (CollectionUtil.isNullOrEmpty(singleMasterOrderPartDTO.getInParts())) {
            notInPart = true;
        }

        // 外报
        boolean notOutPart = false;
        ScmPurchaseApplyQuery scmPurchaseFreightQuery = new ScmPurchaseApplyQuery();
        scmPurchaseFreightQuery.setSourceId(String.valueOf(orderWork.getWorkId()));
        ResponseDTO<List<ScmPurchaseApplyDRO>> listResponseDTO = engineerPurchaseListRemoteService.listByQueryV2(scmPurchaseFreightQuery);
        if (CollectionUtil.isNullOrEmpty(listResponseDTO.getData())) {
            notOutPart = true;
        }

        if (notInPart && notOutPart) {
            throw new OmsBaseException("服务含配件，请选择配件");
        }

    }

    @Override
    public boolean clearEngineerDiscount(OrderWork orderWork, boolean isClearDiscountId) throws OmsBaseException {
        log.info("{}删除计价器3.0工程师优惠 isClearDiscountId={}", orderWork.getWorkId(), isClearDiscountId);

        if (Objects.isNull(orderWork)) {
            throw new OmsBaseException("参数为空");
        }

        if (!Objects.equals(orderWork.getResultStatus(), OrderStatusConsts.WORK_RESULT_DOING) ||
                orderWork.getStatus() >= OrderStatusConsts.WORK_STATUS_COMPLETE) {
            throw new OmsBaseException("工单已完成或取消，不能进行优惠操作");
        }

        OrderQuotationProcess dbProcess = orderQuotationProcessService.findByOrderIdSrcMaster(orderWork.getOrderId());
        if (Objects.isNull(dbProcess)) {
            return false;
        }

        // 判断是否领取工程师优惠
        if (NumberUtil.isNullOrZero(dbProcess.getEngineerDiscountId()) ||
                !Objects.equals(dbProcess.getEngineerDiscountStatus(), GlobalConsts.YES)) {
            return false;
        }

        // 计算和更新工单金额
        ReCalcOrderAmountDIO calcOrderAmountDIO = orderAmountCalcBService.getReCalcOrderAmountDIO(orderWork);
        OrderAmountCalcBO orderAmountCalcBO = orderAmountCalcBService.reCalcOrderAmountAndDiscountAmount(TriggerAmountChangeEnum.ARTIFICIAL_MASTER_DISCOUNT_DELETE, calcOrderAmountDIO, null);
        orderWorkAmountBService.updateAmountAndDiscount(orderAmountCalcBO, orderWork);

        log.info("{}成功删除计价器3.0工程师优惠", orderWork.getWorkId());

        if (!isClearDiscountId) {
            return false;
        }

        // 删除计价器3.0工程师优惠
        OrderQuotationProcess updateProcess = new OrderQuotationProcess();
        updateProcess.setEngineerDiscountId(GlobalConsts.NONE);
        updateProcess.setEngineerDiscountStatus(GlobalConsts.NONE);
        updateProcess.setOrderId(orderWork.getOrderId());
        updateProcess.setUpdateTime(new Date());
        updateProcess.setEngineerDiscountAmount(GlobalConsts.NONE);
        orderQuotationProcessService.updateByOrderIdSelective(updateProcess);
        return true;
    }

    /**
     * 检验用户是否关注
     * @param orderWork 工单信息
     */
    private void checkAttentionWeChat(OrderWork orderWork) throws OmsBaseException{
        OrderThirdAppBind orderThirdAppBind = messageGetSendInfoService.getOrderWeChatBindInfoForOrderBy(orderWork.getOrderId(), orderWork.getPlatWork());
        if (Objects.isNull(orderThirdAppBind) || StringUtils.isBlank(orderThirdAppBind.getThirdAppId())) {
            log.info("订单号{}，未找到绑定公众号信息", orderWork.getWorkId());
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_WECHAT_NO_ATTENTION_CODE, "未找到绑定公众号信息");
        }


        ResponseDTO<Boolean> isAttentionWechat = userThirdListRemoteService.getThirdSubscribeByUserIdAndAppId(orderWork.getVisitUserId(), orderThirdAppBind.getThirdAppId());
        log.info("订单号{},查询用户是否关注公众号,userId:{},appId:{},出参:{}",orderWork.getOrderId(),orderWork.getVisitUserId(),orderThirdAppBind.getThirdAppId(),isAttentionWechat);
        if (isAttentionWechat.isSuccess() && Objects.nonNull(isAttentionWechat.getData())){
            if (!isAttentionWechat.getData()){
                throw new OmsBaseException(OmsErrorCodeConsts.ERROR_WECHAT_NO_ATTENTION_CODE, "发送失败，用户未关注公众号");
            }
        }else {
            log.error("调用getThirdSubscribeByUserIdAndAppId查看用户是否关注公众号接口错误");
            throw new OmsBaseException(OmsErrorCodeConsts.ERROR_WECHAT_NO_ATTENTION_CODE, "查看用户是否关注公众号接口错误");
        }
    }

    /**
     * 保存人工优惠日志
     *
     * @param orderWork 订单信息
     * @param content  日志内容
     */
    private void orderWorkWarrantyAmountLog(OrderWork orderWork, Integer logType, String content,ArtificialDiscountDIO artificialDiscountDIO) {
        if (Objects.isNull(orderWork)) {
            return;
        }
        OrderLog orderLog = new OrderLog();
        orderLog.setWorkId(orderWork.getWorkId());
        orderLog.setOrderId(orderWork.getOrderId());
        orderLog.setType(logType);
        orderLog.setTypeName(OrderLogConsts.getOrderLogTypeName(logType));
        orderLog.setBeforeStatus(orderWork.getStatus());
        orderLog.setBeforeStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setBeforeResultStatus(orderWork.getResultStatus());
        orderLog.setBeforeResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setAfterStatus(orderWork.getStatus());
        orderLog.setAfterStatusName(OrderStatusConsts.getWorkStatusName(orderWork.getStatus()));
        orderLog.setAfterResultStatus(orderWork.getResultStatus());
        orderLog.setAfterResultStatusName(OrderStatusConsts.getWorkResultStatusName(orderWork.getResultStatus()));
        orderLog.setCreateTime(new Date());
        orderLog.setOperatorId((long) artificialDiscountDIO.getMasterId());
        orderLog.setOperator(artificialDiscountDIO.getOperator());
        orderLog.setOperatorType(GlobalConsts.OPERATE_USER_TYPE_MASTER);
        orderLog.setContent(content);
        log.info("#saveDiscount保存人工优惠# 订单号：{}", orderWork.getOrderId());
        orderLogBService.save(orderLog);
    }
}
